package model

import (
	"errors"
	"log"
	"raymond/global"
	"time"

	"github.com/jmoiron/sqlx"
)

const table_bsn_contract_wallets = "t_bsn_contract_wallets"

type BSNContractWallet struct {
	Id           int64     `db:"id"`
	MainWalletId int64     `db:"main_wallet_id"`
	Type         string    `db:"type"`
	Addr         string    `db:"addr"`
	Contract     string    `db:"contract"`
	Token        string    `db:"token"`
	Remark       string    `db:"remark"`
	CreateTime   time.Time `db:"ct"`
	UpdateTime   time.Time `db:"ut"`
}

func (cw *BSNContractWallet) CreateBSNContractWallet() {
	now := time.Now().UTC()
	model := &BSNContractWallet{
		MainWalletId: cw.MainWalletId,
		Type:         cw.Type,
		Addr:         cw.Addr,
		Contract:     cw.Contract,
		CreateTime:   now,
		UpdateTime:   now,
	}
	result, err := global.DB().NamedExec("insert into "+table_bsn_contract_wallets+" (main_wallet_id, type, addr, contract, create_time, update_time)"+
		" values (:main_wallet_id,:type,:addr,:contract,:ct,:ut)",
		&model)
	if err != nil {
		log.Println(err)
		return
	}
	cw.Id, _ = result.LastInsertId()
}

func ListContractWallet(chain global.CHAIN) *[]BSNContractWallet {
	var wallets []BSNContractWallet
	err := global.DB().Select(&wallets, "select id, addr, contract, coalesce(token,0) token from "+table_bsn_contract_wallets+" where type='"+string(chain)+"'")
	if err != nil {
		log.Println(err)
		return nil
	}
	return &wallets
}

func BatchUpdateBSNContractWallet(contractWallets *[]BSNContractWallet) error {
	if contractWallets == nil || len(*contractWallets) <= 0 {
		return errors.New("空数组不能批量更新")
	}
	tx, err := global.DB().Begin()
	if err != nil {
		return err
	}

	defer func() {
		if p := recover(); p != nil {
			log.Println("rollback")
			tx.Rollback()
			panic(p) // re-throw panic
		} else if err != nil {
			log.Println("rollback")
			tx.Rollback()
		} else {
			log.Println("commit")
			err = tx.Commit()
		}
	}()

	updateSql := "update " + table_bsn_contract_wallets + " set token=? WHERE id=?"

	for _, cw := range *contractWallets {
		log.Println(updateSql, cw.Token, cw.Id)
		rs, err := tx.Exec(updateSql, cw.Token, cw.Id)
		if err != nil {
			return err
		}
		effect, err := rs.RowsAffected()
		if err != nil {
			return err
		}
		log.Println("effect", effect)
	}
	return err
}

func BatchInsertBSNContractWallet(contractWallets *[]BSNContractWallet) error {
	if contractWallets == nil || len(*contractWallets) <= 0 {
		return errors.New("空数组不能批量插入")
	}
	now := time.Now().UTC()
	insert := "insert into " + table_bsn_contract_wallets +
		" (main_wallet_id, type, addr, contract, create_time, update_time) values "

	vals := []interface{}{}
	for _, cw := range *contractWallets {
		insert += "(?,?,?,?,?,?),"
		vals = append(vals, cw.MainWalletId, cw.Type, cw.Addr, cw.Contract, now, now)
	}
	// 去掉最后的逗号
	insert = insert[0 : len(insert)-1]

	insert, args, err := sqlx.In(insert, vals...)
	if err != nil {
		return err
	}

	insert = global.DB().Rebind(insert)

	_, err = global.DB().Exec(insert, args...)
	if err != nil {
		return err
	}
	return nil
}
